classdef QAQC_dev < handle
  % Container for all things related to moorings QAQC
  % NOTE: As of 2012-02-09, instances of this class aren't used in any
  %     deployed applications; only its static method: 
  %
  % getCodes(G, RVID, report_state)
  %
  %     is used (in OnTheFlyPlotter_dev).  Its input requirements are:
  %
  %     G: an instance of globals_dev
  %     RVID: RawValueIDs of records whose QAQC codes are desired; 
  %             may be empty
  %     report_state: handle of function to use to report messages
  %
  % Author: David Goldsmith, Wash. State Dept. of Ecology, dgol461@ecy.wa.gov
  % Release date: N/A
    
    properties
        site, SI, P, T, C, S, O
    end
    
    methods
        function oQAQC = QAQC_dev(data)
            oQAQC.site = data{1,2};
            oQAQC.T = data(:,3);
            oQAQC.C = data(:,4);
        end
        
        function assignQAQCcodes(extdata)
            sqlQuery = ['SELECT ValidityStartDatetime ' ...
                        'FROM QAQCTestValues ' ...
                        'WHERE SiteID=''' site ''' and ' ...
                        'ValidityStartDatetime<=''' datestr(datetimes(1)) ''''];
            curs = fetch(exec(conn, sqlQuery));
            if isempty(curs.Message) && ~ischar(curs.Data)
                if ~(length(curs.Data)-1) % if there is only one VSD <= dt1
                    sqlQuery = ['SELECT * FROM QAQCTestValues WHERE SiteID=''' site ...
                                ''' and ValidityStartDatetime=''' curs.Data{1} ''''];
                    curs = fetch(exec(conn, sqlQuery));
                    if isempty(curs.Message) && ~ischar(curs.Data)
                        QAQCparams = cell2struct(curs.Data, ...
                                                {'siteID', 'vsd', 'minSampInt', 'maxSampInt', ...
                                                 'minP', 'maxP', 'minT', 'maxT', 'minC', 'maxC', ...
                                                 'minS', 'maxS', 'minvarS', 'maxvarS', 'minD', 'maxD', ...
                                                 'minO', 'maxO', 'minvarO', 'maxvarO', 'spikeO', ...
                                                 'minFL', 'maxFL', 'minvarFL', 'maxvarFL', 'spikeFL', ...
                                                 'minNTU', 'maxNTU', 'minvarNTU', 'maxvarNTU', 'spikeNTU'}, ...
                                                 2);
                    else
                        report = sprintf('Error querying %s.QAQCTestValues with query:\n\n%s', DB, sqlQuery);
                        reportQueryError(curs, site, report);
                        success = 0;
                        return
                    end    
                else % there is more than one
                    % TODO: implement this case
                end
            else
                report = sprintf('Error querying %s.QAQCTestValues with query:\n\n%s', DB, sqlQuery);
                reportQueryError(curs, site, report);
                success = 0;
                return
            end
        end

        
        function QAQC_tseries = QAQC_tseries(data, param)
            % This creates the time series, for plotting, of QAQC codes
            % data is the array of "y" values, e.g., those of 
            % param, which is one of P, T, S, or O            
        end
    end
    
    methods (Static)
        
        function codes = getCodes(G, RVID, report_state)
          % G: an instance of globals_dev
          % RVID: RawValueIDs of records whose QAQC codes are desired; 
          %         may be empty
          % report_state: handle of function to use to report messages
          
            global conn
            
            codes = {};
%             query = ['SELECT ValidityStartDatetime ' ...
%                      'FROM QAQCTestValues ' ...
%                      'WHERE SiteID=''' G.siteID ''' ' ...
%                      'ORDER BY ValidityStartDatetime'];
%             curs = exec(conn, query);
%             curs = fetch(curs);
%             close(curs);
%             if ~strcmp(curs.Data{1}, 'No Data') && isempty(curs.Message)
%                 validDatetimes = datenum(cell2mat(curs.Data));
%                 allgoodtimes = find(validDatetimes <= G.t_interval(2));
%                 if isempty(allgoodtimes) % start-of-validity of codes lies after the interval
%                     validDatetimes = [];
%                 else
%                     earlygoodtimes = find(validDatetimes < G.t_interval(1));
%                     difference = allgoodtimes - earlygoodtimes;
%                     if isempty(earlygoodtimes) ... % start-of-validity of codes lies inside the interval
%                       || ~any(difference) % allgoodtimes == earlygoodtimes
%                         goodtimes = allgoodtimes;
%                     else % start-of-validity of codes lies before the interval and agt != egt
%                         goodtimes = [max(earlygoodtimes) difference(difference)];
%                     end
%                     validDatetimes = validDatetimes(goodtimes);
%                 end
%             else
%                 validDatetimes = [];
%                 if isempty(curs.Message)
%                     msg = ['No start of validity of QAQC codes data for ' G.siteID];
%                 else
%                     msg = curs.Message;
%                 end
%                 report_state([msg char(10) 'icodes will default to -9_7_0.'], 'DB');
%             end
%             
%             nValidDTs = length(validDatetimes);
            if ~isempty(RVID)
                setdbprefs('DataReturnFormat', 'cellarray')
                s = size(RVID);
    % %            IDQ = [zeros(s)-9; zeros(s)+7; zeros(s)]';
                IDQ = [nans(s); nans(s); nans(s)]';
                PDQ = IDQ; TDQ = IDQ; SDQ = IDQ; ODQ = IDQ;
                if numel(RVID)==1, RVID = [RVID RVID]; end

                query = {['SELECT ' ... %R.RawValueID, R.PostedUTCDatetime, ' ...
                                  'R.SIDataQualVal, R.SIDataQualFlag, R.SIDataQualCtrlLev, ' ...
                                  'R.PresDataQualVal, R.PresDataQualFlag, R.PresDataQualCtrlLev, ' ...
                                  'R.TempDataQualVal, R.TempDataQualFlag, R.TempDataQualCtrlLev, ' ...
                                  'R.SalDataQualVal, R.SalDataQualFlag, R.SalDataQualCtrlLev, ' ...
                                  'C.DO_CalcDataQualVal, C.DO_CalcDataQualFlag, C.DO_CalcDataQualCtrlLev'], ...
                          ['FROM RawValue R inner join CalculatedValue C ' ...
                           'ON R.RawValueID=C.RawValueID'], ...
                          ['WHERE R.RawValueID IN (' sprintf('%d, ', RVID(1:end-1)) ...
                               sprintf('%d', RVID(end)) ') ']};
    %             codes = {};
    %             i = 1;
    %             while i <= nValidDTs % while there are start-of-validity datetimes for the site's codes
    %                 query = baseQuery;
    %                 try
    %                     query{3} = [query{3} ' AND R.PostedUTCDatetime>=''' datestr(validDatetimes(i)) '' ...
    %                                 ' AND R.PostedUTCDatetime<''' datestr(validDatetimes(i+1)) ''''];
    %                 catch
    %                     query{3} = [query{3} ' AND R.PostedUTCDatetime>=''' datestr(validDatetimes(i)) ''''];
    %                 end
                curs = exec(conn, [query{1} ' ' query{2} ' ' query{3}]);
                curs = fetch(curs);
                close(curs);
                if ~strcmp(curs.Data{1}, 'No Data') && isempty(curs.Message)
    %                rvid = cell2mat(curs.Data(:,1));
    %                select = ismember(RVID, rvid);
    %                 IDQ(select,:) = cell2mat(curs.Data(:,3:5));
    %                 PDQ(select,:) = cell2mat(curs.Data(:,6:8));
    %                 TDQ(select,:) = cell2mat(curs.Data(:,9:11));
    %                 SDQ(select,:) = cell2mat(curs.Data(:,12:14));
    %                 ODQ(select,:) = cell2mat(curs.Data(:,15:17));
                    IDQ = cell2mat(curs.Data(:,1:3));
                    PDQ = cell2mat(curs.Data(:,4:6));
                    TDQ = cell2mat(curs.Data(:,7:9));
                    SDQ = cell2mat(curs.Data(:,10:12));
                    ODQ = cell2mat(curs.Data(:,13:15));
                else
                    if isempty(curs.Message)
                        msg = ['No QAQC codes returned for ' G.siteID ...
                               ' in the (perhaps sub-) interval specified.'];
                    else
                        msg = curs.Message;
                    end
    %                report_state([msg char(10) 'Queried codes will default to -9_7_0.'], 'DB');
                    report_state(msg, 'DB');
                end
    %                 i = i + 1;
    %             end
              % Now get code definitions for figure key
                tables = struct('DQV', 'DataQualityValues', ...
                                'DQF', 'DataQualityFlags',  ...
                                'DQC', 'DataQualityControl');
                tableCodes = fieldnames(tables);
                for i=1:length(tableCodes)
                    eval([tableCodes{i} ' = struct();']);
                    query = ['SELECT Value, Definition FROM ' tables.(tableCodes{i})];
                    curs = exec(conn, query);
                    curs = fetch(curs);
                    close(curs);
                    if ~strcmp(curs.Data{1}, 'No Data') && isempty(curs.Message)
                        [nr,~] = size(curs.Data);
                        for j=1:nr
                            val = curs.Data{j}(1);
                            if ischar(val)
                                cmd = strcat(tableCodes{i}, '.(''', strtrim(curs.Data(j,2)), ''') = ''', ...
                                      val, ''';');
                            else
                                cmd = strcat(tableCodes{i}, '.(''', strtrim(curs.Data(j,2)), ''') = ''', ...
                                      int2str(val), ''';');
                            end
                            try
                                eval(cmd{1});
                            catch
                                eval(strrep(cmd{1},'-',''));
                            end
                        end
                    else
                        if isempty(curs.Message)
                            msg = ['No QAQC code definitions returned.' char(10) ...
                                   'Please check your connection to database ' G.DB];
                        else
                            msg = curs.Message;
                        end                
                        report_state([msg char(10) ...
                            'Sorry, QAQC plots legend will be empty.'], 'DB');
                    end
                end
                codes = {IDQ, PDQ, TDQ, SDQ, ODQ, DQV, DQF, DQC};
            end
        end
        
        function pushCodes(site, codes)
            
        end
        
        function crit = getCriteria(site, b, e)

        end
        
    end
    
end